package top.gbiot.scan.controller;

import lombok.Getter;
import lombok.Setter;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import top.gbiot.scan.entity.ApiTemplate;
import top.gbiot.scan.service.IoApiService;
import top.gbiot.scan.service.IoScanAiService;
import top.gbiot.scan.service.IoTableService;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.*;


@Controller
@RequestMapping("/iot/scan")
public class IoScanAiController {

    @Setter
    @Getter
    public  class DeviceInfo{

        String proto; // "http://"

        String method; // "get"

        String ip; // "192.168.124.1"

        String uriInterface; // "/api/get"

        String resBody; // "返回的实际内容"

    }

    String prefix ="iot/scan" ;

    //搜寻到的网上设备
    List<DeviceInfo>  pollDevice = new ArrayList<>();

    @Autowired
    private IoScanAiService scannerService;

    @Autowired
    private IoApiService apiService;

    @Autowired
    private IoTableService ioTableService;

//    @RequiresPermissions("iot:scan:view")
    @GetMapping()
    public String scan(){
        return prefix + "/scanner";
    }


    @PostMapping("/startScanIP")
    public String start( @RequestParam String cidr, Model model ){

        if ( !scannerService.isValidCIDR(cidr)) {
            model.addAttribute("message","地址段格式无效！");
            System.out.println("地址段格式无效！");
        } else {
            ResponseEntity<List<String>> res = scanNetwork(cidr);

            String info ;
            if (Objects.requireNonNull(res.getBody()).isEmpty()) {
                info ="未发现可用的设备IP地址";
            }
            else {
                info ="发现"+res.getBody().size()+"个可用的设备IP地址";
            }

            model.addAttribute("message",info);
            model.addAttribute("items",res.getBody());
            //System.out.println("地址扫描结果："+info);
        }

        if ( !pollDevice.isEmpty()) {
            try {
                //用api搜索device
                scanDevices();
            } catch (IOException e) {
                throw new RuntimeException(e);
            } catch (ExecutionException e) {
                throw new RuntimeException(e);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

            for (DeviceInfo di : pollDevice) {
                //System.out.println(di.getIp()+", body="+di.getResBody());
            }
        }

        return prefix + "/scanner";
    }

    public ResponseEntity<List<String>> scanNetwork( String cidr) {
        ResponseEntity<List<String>> res = ResponseEntity.ok(scannerService.scanActiveDevices(cidr));

        //发现在线设备后收集设备ip，准备api调用
        pollDevice.clear();
        for (int i = 0; i< Objects.requireNonNull(res.getBody()).size(); i++) {
            String ip = res.getBody().get(i);
            System.out.println(ip);
            DeviceInfo di = new DeviceInfo();
            di.setIp(ip);
            di.setMethod("GET");
            di.setUriInterface("/api/device");
            di.setProto("http://");
            pollDevice.add(di);
        }

        //从模板库中生产调用接口参数清单
        List<ApiTemplate> apis = ioTableService.selectApiTemplate();
        System.out.println("api= " + apis.toString());
        return res;
    }

    protected void scanDevices() throws IOException, ExecutionException, InterruptedException {

        ExecutorService executor  = Executors.newFixedThreadPool(20);
        List<Future<String>> futures = new ArrayList<>();
        IoApiService ioApiService = new IoApiService();

        for (int i=0; i< pollDevice.size(); i++) {
            //IoApiService ioApiService = new IoApiService();
            String apiPath = pollDevice.get(i).getProto() + pollDevice.get(i).getIp() + pollDevice.get(i).getUriInterface();
            String method = pollDevice.get(i).getMethod();

            int finalI = i;
            executor.execute(()->{
                String res="";
                try {
                    res= ioApiService.api(apiPath, method);
                    System.out.println("接口反馈："+ res);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                DeviceInfo di= new DeviceInfo();
                di.setResBody(res);
                di.setMethod(method);
                di.setProto(pollDevice.get(finalI).getProto());
                di.setIp(pollDevice.get(finalI).getIp());
                di.setUriInterface(pollDevice.get(finalI).getUriInterface());
                pollDevice.set(finalI,di);
                System.out.println("外部调用 "+ apiPath+", 返回body "+res);
                }
            );

        }
        executor.shutdown();
        try {
            executor.awaitTermination(1, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        System.out.println("----------------------------------------------------------------");
        for ( DeviceInfo di : pollDevice) {
            System.out.println(di.getIp()+" , "+ di.getResBody() );
        }


    }


}
